#include "PyProMessage.h"
#include "ProUIMessage.h"
#include <ProMessage.h>
#include "python.h"	
#include "BindFunction.h"

using namespace pyBind;

static PyObject* PyProUIMessageDialogDisplay( PyObject *self, PyObject *args )
{
	return PyFun<
		Ag<_in>,Ag<_in,WStringTag>,Ag<_in,WStringTag>
		,Ag<_in|_array>,Ag<_in>,Ag<_ret|_adr>
			>(ProUIMessageDialogDisplay,self,args);		
}
	
enum vtypeE { VAT_INT, VAT_DOUBLE, VAT_STRING };

typedef struct {
	vtypeE type;
	union {
		int    ivalue;
		double dvalue;
		wchar_t   wsvalue[1];
	} val;
} vtype;


class ProMessageVarArg
{
public:	
	vtype* argv[10];

	ProMessageVarArg()
	{
		 memset(argv,0,sizeof(vtype*)*10);
	}

	void setVal(int i,long val)
	{
		vtype *av = new vtype;
		av->type = VAT_INT;
		av->val.ivalue = val;
		argv[i] = av;
	}
	void setVal(int i,double val)
	{
		vtype *av = new vtype;
		av->type = VAT_DOUBLE;
		av->val.dvalue = val;
		argv[i] = av;
	}
	void setVal(int i,wchar_t* val)
	{
		size_t s = wcslen(val);
		char* pbuff = new char[sizeof(vtype)+ (s*sizeof(wchar_t))];
		vtype *av = (vtype *)pbuff;
		av->type = VAT_STRING;
		wcscpy_s(av->val.wsvalue,s+1,val);
		argv[i] = av;
	}

	~ProMessageVarArg()
	{
		for(int i = 0; i<10; ++i)
		{
			vtype* arg = argv[i];
			if(arg == NULL)
			{
				break;
			}

			switch(arg->type)
			{
			case VAT_INT:
			case  VAT_DOUBLE:
				delete arg;
				break;
			case VAT_STRING :
				{
					char* pbuff = (char*)arg;
					delete[] pbuff;
				}
			}
		}
	}
	
};

static PyObject* PyProMessageShow( PyObject *self, PyObject *args )
{
	PyObject * message_oA = 0;
	char* msgType = 0;
	if(!PyArg_ParseTuple(args,"O|s:MessageShow", 
		&message_oA
		,&msgType
		))
		return NULL; 

	PyObject *message_o = PyObject_Str(message_oA);
	wchar_t* message = PyUnicode_AS_UNICODE(message_o);

	char* message_name = 0; 
	if(msgType == 0)
	{
		message_name = "Info%0w";
	}
	else
	{
		if(strcmp(msgType,"P") == 0)
		{
			message_name = "Prompt%0w";
		}
		else if(strcmp(msgType,"I") == 0)
		{
			message_name = "Info%0w";
		}
		else if(strcmp(msgType,"W") == 0)
		{
			message_name = "Warning%0w";
		}
		else if(strcmp(msgType,"E") == 0)
		{
			message_name = "Error%0w";
		}
		else if(strcmp(msgType,"C") == 0)
		{
			message_name = "Critical%0w";
		}
		else 
		{
			PyErr_SetString(PyExc_ValueError,"Unsupported Message type");
			return NULL;
		}
	}
	
	ProErr err = ProMessageDisplay(L"pyptkmsg.txt",message_name,message);
	if(PRO_TK_NO_ERROR != err)
	{
		PyErr_SetObject((PyObject *)&pyProErrorType,PyLong_FromLong(err));
		return NULL;
	}
	else
	{
		Py_RETURN_NONE;
	}

	return 0;
}

static PyObject* PyProMessageDisplay( PyObject *self, PyObject *args )
{
	
	PyObject *file_name_o = 0;
	char* message_name = 0;

	PyObject *o1;

	if(!PyArg_ParseTuple(args,"Us|OOOOOOOOOO:ProMessageDisplay", 
		&file_name_o
		,&message_name
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		))
		return NULL; 

	wchar_t* file_name = PyUnicode_AS_UNICODE(file_name_o);


	Py_ssize_t argc = PyTuple_Size(args);
	ProMessageVarArg argv;
	int a = 0;
	for (int i = 2; i < argc; i++,a++) {
		PyObject *o = PyTuple_GetItem(args,i);
		if (PyLong_Check(o)) {
			argv.setVal(a,PyLong_AsLong(o));
		} 
		else if (PyFloat_Check(o)) 
		{
			argv.setVal(a,PyFloat_AsDouble(o));
		} 
		else if (PyUnicode_Check(o)) 
		{
			//argv[i].type = VT_POINTER;
			wchar_t* str = 0;
			str = PyUnicode_AsUnicode(o);
			argv.setVal(a,str);
		} 
		else 
		{
			PyErr_SetString(PyExc_ValueError,"Unsupported argument type");
			return NULL;
		}
	}

	ProErr err = ProMessageDisplay(file_name,message_name
													,&(argv.argv[0]->val)
													,&(argv.argv[1]->val)
													,&(argv.argv[2]->val)
													,&(argv.argv[3]->val)
													,&(argv.argv[4]->val)
													,&(argv.argv[5]->val)
													,&(argv.argv[6]->val)
													,&(argv.argv[7]->val)
													,&(argv.argv[8]->val)
													,&(argv.argv[9]->val)
												);

	if(PRO_TK_NO_ERROR != err)
	{
		PyErr_SetObject((PyObject *)&pyProErrorType,PyLong_FromLong(err));
		return NULL;
	}
	else
	{
		Py_RETURN_NONE;
	}

	return 0;
}

static PyObject* PyProMessageToBuffer( PyObject *self, PyObject *args )
{
	PyObject *file_name_o = 0;
	char* message_name = 0;

	PyObject *o1;

	if(!PyArg_ParseTuple(args,"Us|OOOOOOOOOO:ProMessageDisplay", 
		&file_name_o
		,&message_name
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		,&o1
		))
		return NULL; 

	wchar_t* file_name = PyUnicode_AS_UNICODE(file_name_o);


	Py_ssize_t argc = PyTuple_Size(args);
	ProMessageVarArg argv;
	int a = 0;
	for (int i = 2; i < argc; i++,a++) {
		PyObject *o = PyTuple_GetItem(args,i);
		if (PyLong_Check(o)) {
			argv.setVal(a,PyLong_AsLong(o));
		} else if (PyFloat_Check(o)) {
			argv.setVal(a,PyFloat_AsDouble(o));
		} else if (PyUnicode_Check(o)) {
			//argv[i].type = VT_POINTER;
			wchar_t* str = 0;
			str = PyUnicode_AsUnicode(o);
			argv.setVal(a,str);
		} else {
			PyErr_SetString(PyExc_ValueError,"Unsupported argument type");
			return NULL;
		}
	}
	ProLine translated_msg;
	ProErr err = ProMessageToBuffer(translated_msg,file_name,message_name
		,&(argv.argv[0]->val)
		,&(argv.argv[1]->val)
		,&(argv.argv[2]->val)
		,&(argv.argv[3]->val)
		,&(argv.argv[4]->val)
		,&(argv.argv[5]->val)
		,&(argv.argv[6]->val)
		,&(argv.argv[7]->val)
		,&(argv.argv[8]->val)
		,&(argv.argv[9]->val)
		);
	if(PRO_TK_NO_ERROR != err)
	{
		PyErr_SetObject((PyObject *)&pyProErrorType,PyLong_FromLong(err));
		return NULL;
	}
	else
	{
		return Py_BuildValue("u",translated_msg);
	}

	return 0;
}

static PyObject* PyProMessageIntegerRead( PyObject *self, PyObject *args )
{
	return PyFun<
		Ag<_in|_array>,Ag<_ret|_adr>
	>(ProMessageIntegerRead,self,args);
}
static PyObject* PyProMessageDoubleRead( PyObject *self, PyObject *args )
{
	return PyFun<
		Ag<_in|_array>,Ag<_ret|_adr>
	>(ProMessageDoubleRead,self,args);
}
static PyObject* PyProMessageStringRead( PyObject *self, PyObject *args )
{
	wchar_t outbuff[127];
	ProErr err = ProMessageStringRead(127,outbuff);
	if(PRO_TK_NO_ERROR != err)
	{
		PyErr_SetObject((PyObject *)&pyProErrorType,PyLong_FromLong(err));
		return NULL;
	}
	else
	{
		return Py_BuildValue("U",outbuff);
	}
}

static PyObject* PyProMessagePasswordRead( PyObject *self, PyObject *args )
{
	wchar_t outbuff[127];
	ProErr err = ProMessagePasswordRead(127,outbuff);
	if(PRO_TK_NO_ERROR != err)
	{
		PyErr_SetObject((PyObject *)&pyProErrorType,PyLong_FromLong(err));
		return NULL;
	}
	else
	{
		return Py_BuildValue("U",outbuff);
	}
}
static PyObject* PyProMessageClear( PyObject *self, PyObject *args )
{
	ProMessageClear();
	Py_RETURN_NONE;
}

static PyMethodDef ProMessage_methods[] = {
	{"DialogDisplay", PyProUIMessageDialogDisplay, METH_VARARGS|METH_STATIC,"DialogDisplay."},
	{"IntegerRead", PyProMessageIntegerRead, METH_VARARGS|METH_STATIC,"IntegerRead."},
	{"DoubleRead", PyProMessageDoubleRead, METH_VARARGS|METH_STATIC,"DoubleRead."},
	{"StringRead", PyProMessageStringRead, METH_VARARGS|METH_STATIC,"StringRead."},
	{"PasswordRead", PyProMessagePasswordRead, METH_VARARGS|METH_STATIC,"PasswordRead."},
	{"Display", PyProMessageDisplay, METH_VARARGS|METH_STATIC,"Display."},
	{"ToBuffer", PyProMessageToBuffer, METH_VARARGS|METH_STATIC,"ToBuffer."},
	{"Clear", PyProMessageClear, METH_NOARGS|METH_STATIC,"Clear."},
	{"Show", PyProMessageShow, METH_VARARGS|METH_STATIC,"Show."},
	{NULL}  /* Sentinel */
};

PyTypeObject PyProMessageType = {
	PyVarObject_HEAD_INIT(NULL, 0)
	"Protk.Message",             /* tp_name */
	sizeof(PyProMessage),			/* tp_basicsize */
	0,                         /* tp_itemsize */
	0,                         /* tp_dealloc */
	0,                         /* tp_print */
	0,                         /* tp_getattr */
	0,                         /* tp_setattr */
	0,                         /* tp_reserved */
	0,                         /* tp_repr */
	0,                         /* tp_as_number */
	0,                         /* tp_as_sequence */
	0,                         /* tp_as_mapping */
	0,                         /* tp_hash  */
	0,                         /* tp_call */
	0,                         /* tp_str */
	0,                         /* tp_getattro */
	0,                         /* tp_setattro */
	0,                         /* tp_as_buffer */
	Py_TPFLAGS_DEFAULT,        /* tp_flags */
	"ProMessage objects",           /* tp_doc */
	0,		               /* tp_traverse */
	0,		               /* tp_clear */
	0,		               /* tp_richcompare */
	0,		               /* tp_weaklistoffset */
	0,		               /* tp_iter */
	0,		               /* tp_iternext */
	ProMessage_methods,             /* tp_methods */
	0,             /* tp_members */
	0,                         /* tp_getset */
	0,                         /* tp_base */
	0,                         /* tp_dict */
	0,                         /* tp_descr_get */
	0,                         /* tp_descr_set */
	0,                         /* tp_dictoffset */
	0,      /* tp_init */
	0,                         /* tp_alloc */
	0,                 /* tp_new */

};

int PyInit_ProMessage( PyObject* m)
{
	PyType_Ready(&PyProMessageType);
	Py_INCREF(&PyProMessageType);
	return PyModule_AddObject(m, "Message", (PyObject *)&PyProMessageType);
}
